/**
 * Copyright (C) 2013 DaiKit.com - daikit4gxt module (admin@daikit.com)
 *
 *         Project home : http://code.daikit.com/daikit4gxt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.daikit.daikit4gxt.client.ui;

import com.daikit.commons.shared.bean.DkLanguage;
import com.daikit.daikit4gxt.client.DkBaseMain;
import com.daikit.daikit4gxt.client.action.base.DkBaseShowScreenAction;
import com.daikit.daikit4gxt.client.screen.DkBaseScreen;
import com.daikit.daikit4gxt.client.ui.component.DkTextToolItem;
import com.daikit.daikit4gxt.client.ui.editor.field.DkLanguageChooserComboBox;
import com.gargoylesoftware.htmlunit.javascript.host.Screen;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
import com.sencha.gxt.widget.core.client.ContentPanel;
import com.sencha.gxt.widget.core.client.button.TextButton;
import com.sencha.gxt.widget.core.client.container.BorderLayoutContainer;
import com.sencha.gxt.widget.core.client.container.BorderLayoutContainer.BorderLayoutData;
import com.sencha.gxt.widget.core.client.container.HorizontalLayoutContainer;
import com.sencha.gxt.widget.core.client.container.HorizontalLayoutContainer.HorizontalLayoutData;
import com.sencha.gxt.widget.core.client.container.MarginData;
import com.sencha.gxt.widget.core.client.container.ResizeContainer;
import com.sencha.gxt.widget.core.client.container.SimpleContainer;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData;
import com.sencha.gxt.widget.core.client.container.Viewport;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.form.FormPanel;
import com.sencha.gxt.widget.core.client.form.FormPanel.Method;
import com.sencha.gxt.widget.core.client.toolbar.FillToolItem;
import com.sencha.gxt.widget.core.client.toolbar.SeparatorToolItem;
import com.sencha.gxt.widget.core.client.toolbar.ToolBar;


/**
 * The client side base class for building the application display.<br>
 * This Gui is holding :
 * <ul>
 * <li>The top toolbar with menu items, connection buttons and everything you want to add</li>
 * <li>A screen container in which {@link Screen}s will be loaded</li>
 * </ul>
 * You must extend it to provide you own implementation. <br>
 * The instantiation is made in {@link DkBaseMain}.createGui() method which has to be overridden.
 * 
 * @author tcaselli
 * @version $Revision$ Last modifier: $Author$ Last commit: $Date$
 */
public class DkBaseGui implements UIInvalidatable
{

	protected Viewport viewport;

	protected SimpleContainer screenContainerPanel;

	private final ToolBar tb;
	private TextButton buttonRestoreDown;
	private TextButton buttonExpand;
	private DkTextToolItem displayNameText;

	private final HorizontalLayoutData layoutDataVerticalCenter;

	private final FormPanel hyperlinkCallerFormPanel;
	private final Anchor hyperLink;

	// FOR GUI STANDALONE ----
	private SeparatorToolItem connectSeparatorToolItem;
	private TextButton buttonConnectDisconnect;

	private DkLanguageChooserComboBox languageCombo;

	// ----

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// RENDERING
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	/**
	 * Constructor
	 */
	public DkBaseGui()
	{
		// final Theme themeSlate = new Theme("slate", "Slate", GWT.getHostPageBaseURL() +
		// "gxt/themes/slate/css/xtheme-slate.css");
		// final Theme themeGray = new Theme("gray", GXT.MESSAGES.themeSelector_grayTheme(), GWT.getHostPageBaseURL() +
		// "/gxt/css/gxt-gray.css");
		// ThemeManager.unregister(Theme.GRAY);
		// ThemeManager.register(themeGray);
		// ThemeManager.register(themeSlate);

		viewport = new Viewport();
		RootPanel.get().add(viewport);
		viewport.getElement().getStyle().setPosition(Position.FIXED);
		viewport.getElement().getStyle().setTop(0, Unit.PX);
		viewport.getElement().getStyle().setLeft(0, Unit.PX);
		viewport.getElement().getStyle().setZIndex(1);

		final HorizontalLayoutContainer mainContainer = new HorizontalLayoutContainer();
		viewport.add(mainContainer);
		mainContainer.getElement().getStyle().setProperty("textAlign", "center"); // IE hack for center alignment

		final BorderLayoutContainer mainBorderLayoutContainer = new BorderLayoutContainer()
		{
			@Override
			protected void doLayout()
			{
				super.doLayout();
				getElement().getStyle().setProperty("textAlign", "left"); // clear IE hack
				getElement().getStyle().setProperty("marginTop", "0");
				getElement().getStyle().setProperty("marginRight", "auto");
				getElement().getStyle().setProperty("marginBottom", "0");
				getElement().getStyle().setProperty("marginLeft", "auto");
				getElement().getStyle().setPosition(Position.RELATIVE);
			}
		};
		mainBorderLayoutContainer.setBorders(true);
		layoutDataVerticalCenter = new HorizontalLayoutData(DkBaseMain.model().isFullSize() ? 1 : DkBaseMain.config()
				.getApplicationWidth(), 1, null);
		mainContainer.add(mainBorderLayoutContainer, layoutDataVerticalCenter);

		// NORTH PANEL --------------------------------------------------------------------------

		final VerticalLayoutContainer northPanel = new VerticalLayoutContainer();
		northPanel.setBorders(false);
		tb = new ToolBar();
		updateMainToolBar(tb);
		northPanel.add(tb, new VerticalLayoutData(1, -1));

		final StringBuffer sb = new StringBuffer();
		sb.append("<div class='application-title-container'>");
		sb.append("<img src='" + GWT.getHostPageBaseURL() + DkBaseMain.i18n().appIconPath()).append("'/>");
		sb.append("<span class='app-title'>").append(DkBaseMain.i18n().appTitle()).append("</span>");
		sb.append("<span class='app-title-info'>").append(getAppInfoLabel()).append("</span>");
		sb.append("</div>");
		final HTML titlePanel = new HTML(sb.toString());
		northPanel.add(titlePanel, new VerticalLayoutData(1, -1));

		final BorderLayoutData northBorderLayoutData = new BorderLayoutData(63);
		mainBorderLayoutContainer.setNorthWidget(northPanel, northBorderLayoutData);

		// HYPERLINK FORM PANEL -----------------------------------------------------------------
		hyperlinkCallerFormPanel = new FormPanel();
		hyperlinkCallerFormPanel.setAction("");
		hyperlinkCallerFormPanel.setMethod(Method.POST);
		northPanel.add(hyperlinkCallerFormPanel);

		hyperLink = new Anchor();
		hyperLink.setVisible(false);
		northPanel.add(hyperLink);
		// SCREEN CONTAINER PANEL ---------------------------------------------------------------

		final MarginData centerBorderLayoutData = new MarginData(4, 2, 1, 2);
		screenContainerPanel = new SimpleContainer();
		mainBorderLayoutContainer.add(screenContainerPanel, centerBorderLayoutData);
	}

	private final void updateMainToolBar(final ToolBar tb)
	{
		updateToolbarBeforeStart(tb);
		// Display name text
		tb.add(new FillToolItem());
		updateToolbarBeforeDisplayName(tb);

		if (DkBaseMain.config().isMultiLanguageApplication())
		{
			languageCombo = new DkLanguageChooserComboBox(DkBaseMain.config().isReloadApplicationOnLanguageChange(), DkBaseMain
					.model().getAvailableLanguages());
			languageCombo.setWidth(90);
			tb.add(languageCombo);
			tb.add(new SeparatorToolItem());
		}
		displayNameText = new DkTextToolItem();
		// displayNameText.getElement().getStyle().setFontWeight(FontWeight.BOLD);
		// displayNameText.getElement().getStyle().setFontStyle(FontStyle.ITALIC);
		tb.add(displayNameText);
		updateToolbarBetweenDisplayNameAndConnectButtons(tb);
		updateToolbarConnectButton(tb);
		// button restore down
		buttonRestoreDown = new TextButton("", new SelectEvent.SelectHandler()
		{
			@Override
			public void onSelect(final SelectEvent event)
			{
				DkBaseMain.controller().onFullScreen(false);
			}
		});
		buttonRestoreDown.setIcon(DkBaseMain.icons().restore_down_16_14());
		// button expand
		buttonExpand = new TextButton("", new SelectEvent.SelectHandler()
		{
			@Override
			public void onSelect(final SelectEvent event)
			{
				DkBaseMain.controller().onFullScreen(true);
			}
		});
		buttonExpand.setIcon(DkBaseMain.icons().full_size_16_14());
		tb.add(buttonRestoreDown);
		tb.add(buttonExpand);
	}

	protected void updateToolbarConnectButton(final ToolBar tb)
	{
		if (DkBaseMain.config().isStandalone())
		{
			// Button Connect
			buttonConnectDisconnect = new TextButton("Connect", new SelectEvent.SelectHandler()
			{
				@Override
				public void onSelect(final SelectEvent event)
				{
					if (DkBaseMain.model().isLogged())
					{
						DkBaseMain.controller().doDisconnect();
					}
					else
					{
						DkBaseMain.controller().getConnectionPopupInstance().show();
					}
				}
			});
			buttonConnectDisconnect.setIcon(DkBaseMain.icons().connect_16());
			// Button disconnect

			connectSeparatorToolItem = new SeparatorToolItem();

			tb.add(connectSeparatorToolItem);
			tb.add(buttonConnectDisconnect);
		}
	}

	protected void updateToolbarBeforeStart(final ToolBar tb)
	{
		// Nothing done by default
	}

	protected void updateToolbarBeforeDisplayName(final ToolBar tb)
	{
		// Nothing done by default
	}

	protected void updateToolbarBetweenDisplayNameAndConnectButtons(final ToolBar tb)
	{
		// Nothing done by default
	}

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// GETTERS - SETTERS
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	/**
	 * Remove current screen from container. this method MUST NOT be called directly.<br>
	 * It is called from {@link DkBaseShowScreenAction}.
	 * 
	 * @return a boolean , true if the screen was really removed.
	 */
	public boolean removeCurrentScreenFromContainer()
	{
		boolean ret = false;
		if (DkBaseMain.controller().getCurrentScreen() != null)
		{
			ret = screenContainerPanel.remove(DkBaseMain.controller().getCurrentScreen());
		}
		return ret;
	}

	/**
	 * Call {@link ResizeContainer#forceLayout()} on screen container.
	 */
	public void forceLayoutOnScreen()
	{
		screenContainerPanel.forceLayout();
	}

	/**
	 * Add screen to screen container. This method MUST NOT be called directly.<br>
	 * It is called from {@link DkBaseShowScreenAction}.
	 * 
	 * @param currentScreen
	 *           the screen to be added.
	 */
	public void addScreenToContainer(final DkBaseScreen currentScreen)
	{
		screenContainerPanel.add(currentScreen);
	}

	public Viewport getViewport()
	{
		return viewport;
	}

	public void setViewport(final Viewport viewport)
	{
		this.viewport = viewport;
	}

	public void setScreenContainerPanel(final ContentPanel screenContainerPanel)
	{
		this.screenContainerPanel = screenContainerPanel;
	}

	public void onFullScreenChanged()
	{
		if (DkBaseMain.model().isFullSize())
		{
			layoutDataVerticalCenter.setWidth(1);
		}
		else if (!DkBaseMain.model().isFullSize())
		{
			layoutDataVerticalCenter.setWidth(DkBaseMain.config().getApplicationWidth());
		}
	}

	public FormPanel getHyperlinkCallerFormPanel()
	{
		return hyperlinkCallerFormPanel;
	}

	public Anchor getHyperLink()
	{
		return hyperLink;
	}

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// METHODS
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	@Override
	public void invalidateUi()
	{
		buttonExpand.setEnabled(!DkBaseMain.model().isFullSize());
		buttonExpand.setVisible(!DkBaseMain.model().isFullSize());

		buttonRestoreDown.setEnabled(DkBaseMain.model().isFullSize());
		buttonRestoreDown.setVisible(DkBaseMain.model().isFullSize());

		displayNameText.getElement().getStyle().setPaddingRight(5d, Unit.PX);
		displayNameText.getElement().getStyle().setPaddingRight(5d, Unit.PX);

		languageCombo.setEnabled(DkBaseMain.model().isLogged());

		if (DkBaseMain.config().isStandalone())
		{
			if (DkBaseMain.model().isLogged())
			{
				displayNameText.setText(DkBaseMain.i18n().gui_logged_as_text(getLoggedAsUsername()));
				buttonConnectDisconnect.setText(DkBaseMain.i18n().label_disconnect());
				buttonConnectDisconnect.setIcon(DkBaseMain.icons().disconnect_16());
			}
			else
			{
				displayNameText.setText(DkBaseMain.i18n().gui_user_not_connected());
				buttonConnectDisconnect.setText(DkBaseMain.i18n().label_connect());
				buttonConnectDisconnect.setIcon(DkBaseMain.icons().connect_16());
			}
		}
		else
		{
			displayNameText.setText(DkBaseMain.i18n().gui_logged_as_text(getLoggedAsUsername()));
		}
		displayNameText.syncSize();
		tb.syncSize();
		tb.forceLayout();
	}

	protected String getLoggedAsUsername()
	{
		return DkBaseMain.model().getUserLogged().getEmail();
	}

	protected String getAppInfoLabel()
	{
		return "( F11 : Full Screen )";
	}

	/**
	 * Sets the current {@link DkLanguage} in combo box
	 * 
	 * @param language
	 */
	public void setCurrentLanguage(final DkLanguage language)
	{
		languageCombo.setValue(language);
	}
}
